import Cookies from 'js-cookie'
// eslint-disable-next-line
// import qs from 'qs'
// eslint-disable-next-line
// import $constant from '@/utils/open/constant'
import $validate from '@/utils/open/validate'
// import $eltool from '@/utils/open/eltool'

// const bcrypt = require('bcryptjs') // 引入bcryptjs库
import store from '@/store/index'
import router from '@/router'
// eslint-disable-next-line
import CryptoJS from 'crypto-js'

/**
 * 公用脚本方法类
 */
export default {
    /**
     * 把 NodeList 转成数组
     * @param {NodeList} nodes
     */
    convertToArray(nodes) {
        var array = null
        debugger
        array = []
        for (var i = 0, len = nodes.length; i < len; i++) {
            const val = nodes[i]
            array.push(val)
        }
        return array
    },
    /**
     * 设置公共页标题 面包屑
     * @param {String} title 标题
     */
    setCurPageBreadCurmbTit(title) {
        this.setKeyVal('app', 'curPageTitle', title, 'sessionStorage')
    },
    testFn111(tip) {
        $eltool.warnMsg(tip || '功能正开发中...')
    },
    // 弹窗保存回调 保存表单接口
    /**
     * 弹窗组件调用 保存表单接口
     * @params {String} config 弹窗回调参数
     * @params {Objct} params 参数
     * @params {Function} fn 回调函数
     */
    dialogCallUSaveForm(config, params, fn) {
        // debugger
        // const configName = config.saveFnName
        // console.log('弹窗保存回调', configName, params)
        // // debugger
        // this[configName](params).then(res => {
        //   res = res || {}
        //   // debugger
        //   res.flag = true
        //   fn && fn(res)
        // }).catch((err) => {
        //   err = err || {}
        //   // debugger
        //   err.flag = false
        //   fn && fn(err)
        // })
    },
    /**
     * 导出excel文档
     * @param {String} url
     */
    exportExcel(url) {
        // debugger
        // console.log('exportExcel:',url)
        // 判断是否有id为_exportForm的form表单，如果没有则创建一个隐藏的form，把url放入，然后submit
        var exportForm = document.getElementById('_exportForm')
        if (!exportForm) {
            exportForm = document.createElement('form')
            exportForm.setAttribute('id', '_exportForm')
            exportForm.setAttribute('action', url)
            exportForm.setAttribute('method', 'post')
        }
        document.body.appendChild(exportForm)
        exportForm.submit()
        document.body.removeChild(exportForm) // 导出成功后将form元素移除以免影响下一次导出
    },
    /**
     * 加载语言切换文件
     * @param {Object} that
     * @param {Object} local
     */
    loadI18n(that, local, viewName) {
        // debugger
        // const viewName = $constant.viewName
        if (!that.$i18n.getLocaleMessage('en')[viewName]) {
            that.$i18n.mergeLocaleMessage('en', local.en)
            that.$i18n.mergeLocaleMessage('zh', local.zh)
        }
    },
    /**
     * 清空用户账户数据
     * 退出，密码出错都会执行
     */
    clearAccountFn() {
        const sessionArr = ['navIndex', 'firstUrlParam', 'isCutOutUrl', 'userInfo', 'userResource', 'addRouters', 'originalPermission', 'departTreeData', 'curPageTitle', 'selectOneMenuIndex', 'headPortraitBg', 'isAllowGetListTime', 'isAllowGetListTimeId', 'isNavFold'] // 需要清除的存储数据
        sessionArr.forEach(k => {
            if (k) {
                window.sessionStorage.removeItem(k)
            }
        })
        const localStorageArr = []
        localStorageArr.forEach(k => {
                if (k) {
                    window.localStorage.removeItem(k)
                }
            })
            // debugger
        this.setKeyVal('storeUser', 'userInfo', {}, 'sessionStorage')
        store.dispatch('storeUser/clearToken')

        // 下次的登录，再不关闭浏览器标签的情况下，登陆后直接进到上一次退出的界面
        let path = location.hash
        if (path.indexOf('#') === 0) {
            path = path.substr(1)
        }
        const query = {
            redirect: path
        }
        router.replace({ name: 'Login', query })
    },
    /**
     * 返回首页
     */
    goHomeFn() {
        router.push('/')
    },
    /**
     * 返回上一页
     */
    backFn() {
        console.log('返回上一页')
        router.go(-1)
    },
    // 整合router的name
    initRouterName(routerName) {
        const name = routerName.replace('/', '')
        const lastArr = name.split('-')
        let lastName = ''
        if (lastArr.length) {
            lastArr.forEach(str => {
                    const s1 = str.toLowerCase()
                    const fStr1 = s1.substring(0, 1)
                    const fStr = fStr1.toUpperCase()
                    const lStr = str.substr(1)
                    const s2 = fStr + lStr
                    lastName += s2
                })
                // oRouter.name = lastName
        }
        return lastName
    },
    /**
     * 递归遍历
     * @param {Array} arr 数组
     * @param {String} childName 子级字段名
     */
    recursionArr(arr, childName, fn) {
        arr = arr || []
            // const newArr = []
        for (const obj of arr) {
            // debugger
            const item = childName ? obj[childName] : obj
                // debugger
            fn && fn(item)
            if (Array.isArray(item) && item.length > 0) {
                this.recursionArr(item, childName, fn)
            }
        }
        // return newArr
    },
    recursionLinkStr(arr, object) {
        object = object || {
            str: '',
            arr: []
        }
        arr = arr || []
        const obj = {
            str: '',
            arr: []
        }
        obj.str = object.str
        let str = ''
        for (const item of arr) {
            str = object.str
            if (Array.isArray(item)) {
                const t = this.recursionLinkStr(item, obj)
                if (this.getType(t) === 'string') {
                    obj.str += this.isNotItali(t) ? t : '/' + t
                }
            } else {
                str += this.isNotItali(item) ? item : '/' + item
                $constant.testNoAuth.push(str)
            }
        }
        return object
    },
    isNotItali(str) {
        if (str.indexOf('/') > -1) {
            return true
        } else {
            return false
        }
    },
    /**
     * 加密
     * @returns {string}
     * oldPwd: $2a$10$My07QGXPUGaIrQGRph4SguKiEQqcLgbTByrj/J7NLbLH5wiPMGx8i
     * newPwd: $2a$10$EBvqTkx2apD3x/cSsfUCt./Hv/1Kpp94Y9nKVl.wXvqDVpaTJEi7q
     */
    encryptionFn(value) {
        var bcryptSalt = bcrypt.genSaltSync(10) // 定义密码加密的计算强度,默认10
        var hash = bcrypt.hashSync(value, bcryptSalt) // 把自己的密码(this.registerForm.passWord)带进去,变量hash就是加密后的密码
        return hash
    },
    encrypt(word, keyStr) {
        keyStr = keyStr || 'hxcloud-client12' // 判断是否存在ksy，不存在就用定义好的key
        var key = CryptoJS.enc.Utf8.parse(keyStr)
        var srcs = CryptoJS.enc.Utf8.parse(word)
        var encrypted = CryptoJS.AES.encrypt(srcs, key, {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        })
        return encrypted.toString()
    },
    /**
     * 获取uuid
     * @returns {string}
     */
    uuid() {
        function S4() {
            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
        }
        return (
            S4() +
            S4() +
            '-' +
            S4() +
            '-' +
            S4() +
            '-' +
            S4() +
            '-' +
            S4() +
            S4() +
            S4()
        )
    },
    /**
     * 在不刷新页面的情况下，修改url参数
     * @param {Object} data
     *  主要方法h5的 pushState(replaceState 和 pushState 唯一的区别：replaceState不会新增历史，pushState会新增历史)
     *  stateObject:JavaScript对象，通过pushState方法可以将stateObject内容传递到新页面中;
     *  title: 几乎没有浏览器支持该参数，但是传一个空字符串会比较安全。
     *  url: 新的历史记录条目的地址（可选，不指定的话则为文档当前URL）；浏览器在调用pushState()方法后不会加载该地址；传入的URL与当前URL应该是同源的，否则，pushState()会抛出异常。
     * @param {Object} config
     */
    onlyModifyParamsOnUrl(data, config) {
        config = config || {}
            // const tt = window.location
        let url = ''
        let len = ''
        if ($constant.isRouterHistory) {
            // router history mode
            // debugger
            url = location.href
            len = url.indexOf('?')
        } else {
            // router hash mode
            // debugger
            url = location.hash
            len = url.indexOf('?')
        }

        if (len !== -1) {
            url = url.substring(0, len)
        }

        const str = this.obj2Str(data)
        url += str
        if (config.isReplace) {
            history.replaceState({}, '', url)
        } else {
            history.pushState({}, '', url)
        }
    },
    /**
     * 节流函数: 指定时间间隔内只会执行一次任务
     * @param {function} fn
     * @param {Number} interval
     */
    throttle(fn, interval = 300) {
        let canRun = true
            // console.log('节流-throttle-1')
        return function() {
            // console.log('节流-throttle-2')
            if (!canRun) return
            canRun = false
            setTimeout(() => {
                // console.log('节流-throttle-3')
                fn.apply(this, arguments)
                canRun = true
            }, interval)
        }
    },
    /**
     * 防抖: 指定时间间隔内只会执行一次任务，并且该时间段内再触发，都会重新计算时间。(函数防抖的非立即执行版)
     * 在频繁触发某些事件，导致大量的计算或者非常消耗资源的操作的时候，防抖可以强制在一段连续的时间内只执行一次
     * */
    debounce(fn, delay) {
        // console.log('防抖-debounce-1')
        const _delay = delay || 200
        let timer
        return function() {
            // console.log('防抖-debounce-2')
            const th = this
            const args = arguments
            if (timer) {
                clearTimeout(timer)
            }
            timer = setTimeout(function() {
                timer = null
                fn.apply(th, args)
                    // console.log('防抖-debounce-3')
            }, _delay)
        }
    },
    /**
     * 对象转url str
     * 只支持一级obj
     */
    obj2Str(obj) {
        // debugger
        if ($validate.isNull(obj)) {
            return ''
        }
        let str = ''
        const unique = {}
        for (const key in obj) {
            // debugger
            if (!unique[key] && key && obj.hasOwnProperty(key)) {
                unique[key] = true
                let val = obj[key]
                    // if (this.checkChinese(val)) {
                val = encodeURIComponent(val)
                    // }
                str += '&' + key + '=' + val
            }
        }
        str = '?' + str.substr(1)
        return str
    },
    // str转json对象
    str2Obj(str) {
        const newObj = {}
        if (str) {
            const sysbolIndex = str.lastIndexOf('?')
            if (sysbolIndex > -1) {
                // 有？则从?后开始截取
                str = str.substr(1)
            }

            const obj = str.split('&')
            let arr = []
            for (const key of obj) {
                arr = key.split('=')
                newObj[arr[0]] = arr[1]
            }
        }
        return newObj
    },
    /**
     * 数组转对象，深拷贝
     * @param {array} arr 数组
     * @param {String} keyName colname
     * @param {String} valueName value
     */
    arr2Obj(arr, keyName, valueName) {
        arr = arr || []
        let obj = {}
        debugger
        arr.forEach(item => {
            if (Array.isArray(item)) {
                const obj1 = this.arr2Obj(item)
                debugger
                obj = this.deepCloneObj(obj1)
                debugger
            } else {
                if (keyName) {
                    const value = item[valueName]
                    obj[keyName] = value
                } else {
                    const key = item.colname
                    const value = item.value
                    obj[key] = value
                    debugger
                    // for (const key in item) {
                    //   const value = item[key]
                    //   obj[key] = value
                    //   debugger
                    // }
                }
            }
        })
        return obj
    },
    // 查找两个数组的不同
    getArrDifference(arr1, arr2) {
        return arr1.concat(arr2).filter(function(v, i, arr) {
            return arr.indexOf(v) === arr.lastIndexOf(v)
        })
    },
    // 字符串拼接
    /**
     * @param {String} str1
     * @param {Array} arr
     * @return {String} str
     */
    splitStr(str1, arr) {
        let str = !str1 ? '' : str1.toString()
        if (arr.length <= 0) return str
        arr.forEach(item => {
            str += ' ' + item
        })
        return str.trim()
    },
    /**
     * 获取链接末尾参数
     * @param {string}  num：1. hash
     */
    getCurPathParam(num) {
        // debugger
        const newObj = {}
        if (num === 1) {
            const url = location.hash // 获取链接 #/...? 后的字符串，并组合成 json 格式
            const reg = /#\/.*?\?/gi

            // if(url.indexOf('?') !== -1){
            const res = url.match(reg)
                // debugger
            if (res && url.match(reg).length > 0) {
                // let str = url.substr(3);
                let str = url.replace(reg, '')
                str = str.replace(/#\/$/, '')
                const strs = str.split('&')
                for (let i = 0; i < strs.length; i++) {
                    const key = strs[i].split('=')[0]
                    const value = strs[i].split('=')[1]
                    newObj[key] = decodeURIComponent(value)
                }
            }
        } else {
            let url = location.search // 获取链接 #/...? 后的字符串，并组合成 json 格式
            if (url) {
                url = url.substr(1)
                const obj = url.split('&')
                let arr = []
                for (const key of obj) {
                    arr = key.split('=')
                    newObj[arr[0]] = arr[1]
                }
            }
        }
        return newObj
    },
    /**
     * 存储 store , sessionStorage
     * 注意传参格式
     * @param {String} module
     * @param {String} key
     * @param {String} val
     * @param {String} storeName 可不传 localStorage,sessionStorage
     */
    setKeyVal(module, key, val, storeName) {
        const fnName =
            module + '/Update' + key.substring(0, 1).toUpperCase() + key.substring(1)
            // debugger
        const type = $validate.judgeTypeOf(val)
        if (type !== 'String' && type !== 'Undefined' && type !== 'Null') {
            store.dispatch(fnName, val)
            if (storeName) {
                let val1 = this.deepCloneObj(val)
                val1 = JSON.stringify(val1)
                window[storeName].setItem(key, val1)
            }
        } else {
            if (storeName) {
                window[storeName].setItem(key, val)
            }

            try {
                if (val.match(/\{/)) {
                    // 若匹配到{则说明是json字符
                    val = JSON.parse(val)
                }
            } catch (e) {
                // dosome...
            } finally {
                if (type === 'String') {
                    store.dispatch(fnName, val)
                }
            }
        }
    },
    /**
     * 获取 store,sessionStorage
     * @param {String} module 模块名字
     * @param {String} key state属性
     * @param {Boolean} storeName localStorage,sessionStorage
     */
    getKeyVal(module, key, storeName) {
        let val = store.state[module][key]
            // debugger
        if ($validate.isNull(val) && !$validate.isNull(storeName)) {
            val = window[storeName].getItem(key)
            if (!$validate.isNull(val)) {
                this.setKeyVal(module, key, val)

                const type = $validate.judgeTypeOf(val)
                if (type === 'String' && val.match(/\{/)) {
                    // 若匹配到{则说明是json字符
                    val = JSON.parse(val)
                }
            }
        }
        return val
    },
    /**
     * 设置 临时 缓存
     * @param key
     * @param value
     */
    setSession(key, value) {
        // debugger
        return new Promise((resolve, reject) => {
            try {
                window.sessionStorage.setItem(key, JSON.stringify(value))
                resolve()
            } catch (e) {
                console.error('setSession 错误')
                reject('setSession 错误')
            }
        })
    },
    /**
     * 获取 临时 缓存
     * @param key
     */
    getSession(key) {
        const item = window.sessionStorage.getItem(key)
        if ($validate.isNull(item)) {
            return ''
        }
        return JSON.parse(window.sessionStorage.getItem(key))
    },
    /**
     * 设置 永久 缓存
     * @param key
     * @param value
     */
    setLocalStorage(key, value) {
        // debugger
        return new Promise((resolve, reject) => {
            try {
                window.localStorage.setItem(key, JSON.stringify(value))
                resolve()
            } catch (e) {
                console.error('setSession 错误')
                reject('setSession 错误')
            }
        })
    },
    /**
     * 获取 永久 缓存
     * @param key
     */
    getLocalStorage(key) {
        const item = window.localStorage.getItem(key)
        if ($validate.isNull(item)) {
            return ''
        }
        return JSON.parse(window.localStorage.getItem(key))
    },
    /**
     * 获取 cookie
     * @param key
     */
    getCookie(key) {
        return Cookies.get(key)
    },
    /**
     * 设置 cookie
     * @param key
     */
    setCookie(key, val) {
        return Cookies.set(key, val)
    },
    /**
     * 删除 cookie
     * @param key
     */
    removeCookie(key) {
        return Cookies.set(key)
    },
    /**
     * 对象，浅拷贝
     * @param {Object} obj
     */
    easyCloneObj(obj) {
        const newObj = {}
        for (const i in obj) {
            if (i && obj.hasOwnProperty(i)) {
                newObj[i] = obj[i]
            }
        }
        return newObj
    },
    /**
     * 对象，深拷贝
     * @param {Object} obj
     */
    deepCloneObj(data) {
        const type = this.getType(data)
        let obj
        if (type === 'array') {
            obj = []
        } else if (type === 'object') {
            obj = {}
        } else {
            return data
        }
        if (type === 'array') {
            for (let i = 0, len = data.length; i < len; i++) {
                obj.push(this.deepCloneObj(data[i]))
            }
        } else if (type === 'object') {
            for (const key in data) {
                if (data.hasOwnProperty(key)) {
                    obj[key] = this.deepCloneObj(data[key])
                }
            }
        }
        return obj
    },
    /**
     * 复制对象公共属性的值
     * @param {Object} obj1 拷贝的对象
     * @param {Array} arr 被拷贝的数组对象
     */
    copyObjComVal(obj1, arr) {
        // debugger
        if ($validate.isNull(obj1) && $validate.isNull(arr)) {
            return obj1
        }
        // debugger
        for (let obj2 of arr) {
            obj2 = obj2 || {}
            if ($validate.isNull(obj2)) {
                continue
            }
            for (const key in obj1) {
                if (key && obj2.hasOwnProperty(key)) {
                    obj1[key] = obj2[key]
                }
            }
        }

        return obj1
    },
    /**
     * 复制对象属性
     * @param {Object} obj1 拷贝的对象
     * @param {Array} arr 被拷贝的数组对象
     */
    copyObjVal(obj1, arr) {
        // debugger
        if ($validate.isNull(obj1) && $validate.isNull(arr)) {
            return obj1
        }
        // debugger
        for (let obj2 of arr) {
            obj2 = obj2 || {}
            if ($validate.isNull(obj2)) {
                continue
            }
            for (const key in obj2) {
                if (key && obj2.hasOwnProperty(key)) {
                    obj1[key] = obj2[key]
                }
            }
        }

        return obj1
    },
    /**
     * 删除Object的某些属性
     * @param {Object} O
     * @param {Array} arr
     */
    rmProByKey(O, arr) {
        for (const key of arr) {
            delete O[key]
        }
    },
    // 正则表达式截取html标签内的内容
    getHtmlText(val) {
        const reg = /<[^<>]+>/g
        val = val.replace(reg, '')
        val = val.replace(/&nbsp;/g, ' ')
            // val = this.faceTopic2Img(val)
        return val
    },
    /**
     * 获取对象属性类型
     * @param e
     * @returns {string}
     */
    getType(value) {
        var type = ''
            // if (value == null) {
            //   return type
            // }
        if (typeof value !== 'object') {
            type = typeof value
                // debugger
        } else {
            // debugger
            if (value instanceof Array) {
                type = 'array'
            } else if (value instanceof Object) {
                type = 'object'
            } else if (value instanceof Function) {
                type = 'function'
            } else {
                type = 'null'
            }
        }
        return type

        // if (value.constructor === Array) {
        //   return 'array'
        // } else if (value.constructor === Object) {
        //   return 'object'
        // } else if (value.constructor === String) {
        //   return 'string'
        // } else if (value.constructor === Number) {
        //   return 'number'
        // } else if (value.constructor === Boolean) {
        //   return 'boolean'
        // }
        // return ''
    },
    /**
     * 获取dom元素style
     * @param dom
     * @param attr
     */
    getStyle(dom, attr) {
        // debugger
        if (dom.currentStyle) {
            return dom.currentStyle[attr]
        } else {
            return getComputedStyle(dom, null)[attr]
        }
    },
    /**
     * 查找父元素
     * @param {Object} child 目标dom元素
     * @param {String} parentCls 父元素的class
     */
    getParentByClass(child, parentCls) {
        if (!child) {
            return child
        }

        if (child.classList.contains(parentCls)) {
            return child
        }

        const pNode = child.parentNode
        if (pNode.classList.length && pNode.classList.contains(parentCls)) {
            return pNode
        } else {
            return this.getParentByClass(pNode, parentCls)
        }
    },
    /**
     * 获取元素的位置以及大小
     * @param {Object} el dom
     */
    getRect(el) {
        if (!el) {
            return false
        }
        if (el instanceof window.SVGElement) {
            const rect = el.getBoundingClientRect()
            return {
                top: rect.top,
                left: rect.left,
                width: rect.width,
                height: rect.height
            }
        } else {
            return {
                top: el.offsetTop,
                left: el.offsetLeft,
                width: el.offsetWidth,
                height: el.offsetHeight
            }
        }
    },
    getComputedStyleFn(el, attr) {
        //    兼容IE和火狐谷歌等的写法
        let attrVal = {}
            // debugger
        if (window.getComputedStyle) {
            // attrVal = parseInt(getComputedStyle(el, attr))
            attrVal = getComputedStyle(el, null)
        } else {
            attrVal = el.currentStyle // 兼容IE的写法
        }
        return attrVal
    },
    /**
     * 通过数组键值删除元素
     * @param {Array} arr 数组
     * @param {String} key 匹配的键
     * @param {String} val 匹配的值
     */
    removeByKey(arr, key, val) {
        const index = this.findKey(arr, key, val)
        if (index > -1) {
            arr.splice(index, 1)
        }
    },
    /**
     * 返回数组匹配到的索引
     * @param {Array} arr 数组
     * @param {String} key 匹配的键
     * @param {String} val 匹配的值
     * @return {Number} index 返回匹配到的索引
     */
    findKey(arr, key, val) {
        for (let i = 0; i < arr.length; i++) {
            const item = arr[i]
            if (item[key] === val) {
                return i
            }
        }
        return -1
    },
    findEleParentNode(el, parentName, parentArr) {
        if (!el) {
            return el
        }
        // debugger
        parentName = parentName || 'BODY'
        parentArr = parentArr || []
        const parentNode = el.parentNode
        parentArr.push(parentNode)
            // debugger
        if (parentNode.nodeName !== parentName) {
            return this.findEleParentNode(parentNode, parentName, parentArr)
        }
        // debugger
        return parentArr
    },
    // TODO:待完善
    // 查找所有匹配的父级
    findEleParentAllNode(el, parentName, parentArr) {
        if (!el) {
            return el
        }
        parentArr = parentArr || []
        const parentNode = el.parentNode
            // let attrType = ''
        let attrName = parentName || 'BODY'
        let bool = false
        debugger
        if (attrName.indexOf('.')) { // class
            // attrType = 'class'
            attrName = attrName.replace('.', '')
            bool = parentNode.classList.contains(attrName)
        } else if (attrName.indexOf('#')) { // id
            // attrType = 'id'
            attrName = attrName.replace('#', '')
            bool = parentNode.id === attrName
        } else { // 元素名称
            const parentNodeName = parentNode.nodeName
            bool = parentNodeName === attrName
        }
        if (bool) {
            parentArr.push(parentNode)
        }

        if (parentNode.nodeName !== attrName) {
            return this.findEleParentAllNode(parentNode, attrName, parentArr)
        }
        // debugger
        return parentArr
    },
    // 查找兄弟级元素，并返回
    /**
     * 查找兄弟级元素，并返回
     * @param {Node} el
     * @param {Array} ExceptArr 排除个别node 有.的是class，有#的是id,都没有的是标签名
     */
    findSiblingsEle(el, ExceptArr) {
        if (!el) {
            return el
        }
        const pDom = el.parentNode
        const childArr = pDom.children // 获取到所有的子元素
            // node.children 转为数组
        let array = null
        try {
            array = Array.prototype.slice.call(childArr, 0)
        } catch (ex) {
            array = []
            for (var i = 0, len = childArr.length; i < len; i++) {
                array.push(childArr[i])
            }
        }
        // debugger
        // 排除个别子元素
        if (ExceptArr && Array.isArray(ExceptArr) && ExceptArr.length > 0) {
            for (const attrName of ExceptArr) {
                // debugger
                for (var j = 0; j < array.length; j++) {
                    const o = array[j]
                    let bool = false
                        // debugger
                    if (this.isDOMFn(attrName)) {
                        // debugger
                        bool = o === attrName
                    } else if (attrName.indexOf('.') > -1) {
                        const t = attrName.replace('.', '')
                        if (o.classList.contains(t)) {
                            bool = true
                        }
                    } else if (attrName.indexOf('#') > -1) {
                        var t = attrName.replace('#', '')
                            // debugger
                        if (o.id === t) {
                            bool = true
                        }
                    }

                    if (bool) {
                        array.splice(j, 1)
                            --j
                    }
                    // if (o.classList.contains(attrName)) {
                    //   // debugger
                    //   array.splice(j, 1)
                    //   --j
                    //   // debugger
                    // }
                }
            }
        }

        // debugger
        return array
    },
    // 首先要对HTMLElement进行类型检查，因为即使在支持HTMLElement的浏览器中，类型却是有差别的，在Chrome,Opera中HTMLElement的类型为function，此时就不能用它来判断了
    isDOMFn(dom) {
        let bool = false
            // debugger
        if (HTMLElement === 'object') {
            bool = dom instanceof HTMLElement
        } else {
            if (dom && typeof dom === 'object' && dom.nodeType === 1 && typeof dom.nodeName === 'string') {
                bool = true
            }
        }
        return bool
    },
    /**
     * 将FORM的数据转成FieldValue类型的数据
     * @param {Object,Array} data  FORM转入值
     */
    copyDataToFieldValue(data) {
        var arr = []
            // debugger
        const type = this.getType(data)
        if (type === 'array') {
            for (const item of data) {
                arr = arr.concat(this.copyDataToFieldValue(item))
            }
        } else if (type === 'object') {
            for (var key in data) {
                // debugger
                if (key.indexOf('noSaveKey_') === -1) { //  // noSaveKey_是前端自定义字段名，不作为提交保存的标识
                    const value = this.getParamsLastVal(data[key]) // // 将传参为json中的值为数组的，取数组最后一项
                    arr.push({ name: key, value: '' + value })
                }
            }
        } else {
            arr.push([{ name: 'test-todo-ttt', value: 'copyDataToFieldValue方法-test有空值' }])
        }

        return arr
    },
    // 将传参json中的值为数组的取数组最后一项
    getParamsLastVal(data) {
        // debugger
        const type = this.getType(data)
        if (type === 'array') {
            const len = data.length
            data = data[len - 1]
        }
        return data
    },
    // 比较并初始化提交保存数据
    /**
     * @param {Object} listItem gropus.list => [item]
     * @param {Object} originData 原始值
     * @param {Object} curData 当前变化的值
     * @return {Array} data 返回数据
     */
    compareInitData(listItem, originData, curData) {
        const data = []
        const hasListItem = !$validate.isNull(listItem)
            // debugger
            /* 比对两次数据，取得修过以后的数据项*/
        for (let i = 0; i < originData.length; i++) {
            const obj1 = originData[i]
            const obj2 = curData[i]
                // debugger
            for (const key in obj2) {
                // const t = key.indexOf('noSaveKey_')
                // if (key.indexOf('PERSONLIABLE') > -1) {
                //   debugger
                // }
                if (obj2.hasOwnProperty(key) && key.indexOf('noSaveKey_') === -1) {
                    // noSaveKey_是前端自定义字段名，不作为提交保存的标识
                    const value1 = obj1[key]
                    let value2 = obj2[key]

                    // TODO:这里需要考虑多种可能
                    // 值是数组，级联选择器，会返回一个数组得值（比如：部门下拉框）
                    const type = this.getType(value2)
                    if (type === 'array') {
                        value2 = value2[value2.length - 1]
                    }
                    if ((!$validate.isNull(value1) || !$validate.isNull(value2)) && value1 !== value2) {
                        // debugger
                        const obj = {
                            colname: key,
                            value: value2
                        }
                        data.push(obj)
                        if (hasListItem) {
                            this.updateListItem(listItem, key, value2)
                        }
                    }
                }
            }
        }
        return data
    },
    // 更新列表显示 formData
    updateListItem(listItem, key, value2) {
        listItem.list.some(O => {
            if (O.colName === key) {
                // debugger
                O.value = value2
                const dropList = O.dropList || []
                dropList.some(dItem => {
                    if (dItem.value === value2) {
                        O.text = dItem.label
                        return true
                    }
                })
                return true
            }
        })
    },
    // 获取浏览器信息
    getBrowserInfo(n) {
        var ua = navigator.userAgent.toLowerCase()
        let s = ''
        let name = ''
        let ver = 0
            // eslint-disable-next-line
        ;
        (s = ua.match(/msie ([\d.]+)/)) ?
        _set('ie', _toFixedVersion(s[1])): (s = ua.match(/firefox\/([\d.]+)/)) ?
            _set('firefox', _toFixedVersion(s[1])) :
            (s = ua.match(/chrome\/([\d.]+)/)) ?
            _set('chrome', _toFixedVersion(s[1])) :
            (s = ua.match(/opera.([\d.]+)/)) ?
            _set('opera', _toFixedVersion(s[1])) :
            (s = ua.match(/version\/([\d.]+).*safari/)) ?
            _set('safari', _toFixedVersion(s[1])) :
            0

        function _toFixedVersion(ver, floatLength) {
            ver = ('' + ver).replace(/_/g, '.')
            floatLength = floatLength || 1
            ver = String(ver).split('.')
            ver = ver[0] + '.' + (ver[1] || '0')
            ver = Number(ver).toFixed(floatLength)
            return ver
        }

        function _set(bname, bver) {
            name = bname
            ver = bver
        }
        return n === 'n' ? name : n === 'v' ? ver : name + ver
    }
}
// export function oneOf (value, validList) {
//   for (let i = 0; i < validList.length; i++) {
//     if (value === validList[i]) {
//       return true
//     }
//   }
//   return false
// }

// var t = [
//   {
//     label: '第一周',
//     value: ['2020-10-01', '2020-10-07']
//   },
//   {
//     label: '第二周',
//     value: ['2020-10-08', '2020-10-14']
//   }
// ]